<!-- DataTable.vue（完整单选限制版） -->
<script setup>
import { ref, watch, computed, onMounted } from 'vue'

// 定义事件：发射选中的ID数组（确保父组件接收）
const emit = defineEmits(['update:selectedIds'])

const props = defineProps({
  dataSource: {
    type: Array,
    required: true,
    default: () => []
  },
  columns: {
    type: Array,
    required: true,
    default: () => []
  },
  showCheckbox: {
    type: Boolean,
    default: false
  },
  defaultSelectedIds: {
    type: Array,
    default: () => []
  },
  checkboxWidth: {
    type: Number,
    default: 30
  },
  // 新增：控制是否开启“只能选一个”限制（默认关闭，按需开启）
  isSingleSelect: {
    type: Boolean,
    default: false
  }
})

// 内部选中ID数组（与父组件defaultSelectedIds同步）
const selectedIds = ref([])
// 全选状态（单选限制开启时自动失效）
const allSelected = ref(false)

// 1. 统一状态同步方法：处理defaultSelectedIds和dataSource变化
const syncSelectedState = () => {
  // 同步选中ID：确保是数组，避免父组件传入非数组
  selectedIds.value = Array.isArray(props.defaultSelectedIds)
    ? [...props.defaultSelectedIds]
    : []

  // 处理单选限制：若开启，强制父组件默认选中不超过1个
  if (props.isSingleSelect && selectedIds.value.length > 1) {
    selectedIds.value = selectedIds.value.slice(-1) // 只保留最后一个默认选中项
    // 同步给父组件（避免父组件默认值与子组件不一致）
    emit('update:selectedIds', [...selectedIds.value])
  }

  // 同步全选状态：单选限制开启时，全选框强制未勾选
  allSelected.value = !props.isSingleSelect
    ? (props.dataSource.length > 0 && props.dataSource.every(item => selectedIds.value.includes(item.id)))
    : false
}

// 2. 组件初始化时同步状态
onMounted(() => {
  syncSelectedState()
})

// 3. 监听父组件传递的props变化（默认选中/数据源变化时同步）
watch(
  [() => props.defaultSelectedIds, () => props.dataSource, () => props.isSingleSelect],
  () => {
    syncSelectedState()
  },
  { deep: true } // 监听数组内部元素变化
)

// 4. 监听内部选中状态变化：同步全选+发射给父组件
watch(
  selectedIds,
  (newVal) => {
    // 防御：确保是数组
    if (!Array.isArray(newVal)) {
      selectedIds.value = []
      return
    }

    // 单选限制处理：若开启且超过1个，自动截取最后一个
    if (props.isSingleSelect && newVal.length > 1) {
      selectedIds.value = newVal.slice(-1) // 删除前N-1个，保留最后一个
      return // 终止后续逻辑，避免重复发射
    }

    // 更新全选状态（单选限制开启时全选无效）
    allSelected.value = !props.isSingleSelect
      ? (props.dataSource.length > 0 && props.dataSource.every(item => newVal.includes(item.id)))
      : false

    // 发射最新选中数组给父组件（深拷贝，避免引用问题）
    emit('update:selectedIds', [...newVal])
  },
  { deep: true }
)

// 5. 全选/取消全选（单选限制开启时禁用）
const handleSelectAll = () => {
  if (props.isSingleSelect) {
    return
  }

  selectedIds.value = allSelected.value
    ? props.dataSource.map(item => item.id) // 全选：取所有ID
    : [] // 取消全选：清空
}

// 6. 单选处理（核心：单选限制逻辑）
const handleSelect = (id) => {
  // 防御：确保选中数组是数组
  if (!Array.isArray(selectedIds.value)) {
    selectedIds.value = []
  }

  const index = selectedIds.value.indexOf(id)
  if (index === -1) {
    // 新勾选：单选限制开启时，直接替换现有选中项
    if (props.isSingleSelect) {
      selectedIds.value = [id] // 替换（删除之前的选中项）
    } else {
      selectedIds.value = [...selectedIds.value, id] // 正常添加（多选模式）
    }
  } else {
    // 取消勾选：从数组中移除当前ID
    selectedIds.value = selectedIds.value.filter(itemId => itemId !== id)
  }
}

// 7. 计算列宽样式（与columns宽度配置同步）
const columnStyles = computed(() => {
  return props.columns.map(col => col.width ? { width: `${col.width}px`, minWidth: `${col.width}px` } : {})
})

// 8. 计算多选框列宽样式
const checkboxStyle = computed(() => ({
  width: `${props.checkboxWidth}px`,
  minWidth: `${props.checkboxWidth}px` // 防止缩窄
}))
</script>

<template>
  <div class="flex flex-col rounded-sm text-sm font-medium">
    <!-- 表格：边框合并+100%宽度 -->
    <table class="border-collapse w-full">
      <!-- 表头：灰色背景 -->
      <thead class="bg-[#f2f3f5]">
        <tr>
          <!-- 多选框列：单选限制开启时隐藏，showCheckbox为true时显示 -->
          <th v-if="showCheckbox && !isSingleSelect" :style="checkboxStyle"
            class="text-left p-[10px_8px_10px_14px] border-b border-[#e5e6eb] h-[41px] transition-all">
            <div class="flex items-center">
              <!-- 隐藏原生复选框，用自定义样式替代 -->
              <input type="checkbox" class="hidden" v-model="allSelected" @change="handleSelectAll" />
              <div
                class="w-4 h-4 border border-gray-300 rounded cursor-pointer flex items-center justify-center transition-colors"
                :class="{ 'bg-blue-500 border-blue-500': allSelected }" @click="handleSelectAll">
                <span v-if="allSelected" class="text-white text-xs">✓</span>
              </div>
            </div>
          </th>

          <!-- 单选框列：单选限制开启时显示，showCheckbox为true时显示 -->
          <th v-if="showCheckbox && isSingleSelect" :style="checkboxStyle"
            class="text-left p-[10px_8px_10px_14px] border-b border-[#e5e6eb] h-[41px] transition-all">
            <div class="flex items-center justify-center">
              <!-- 单选模式下显示“选择”提示，无全选框 -->
              <span class="text-gray-600 text-xs">选择</span>
            </div>
          </th>

          <!-- 列标题：循环渲染columns配置 -->
          <th v-for="(column, index) in columns" :key="column.dataIndex || index" :style="columnStyles[index]"
            class="text-left p-[10px_8px_10px_14px] border-b border-[#e5e6eb] h-[41px] transition-all">
            {{ column.title }}
          </th>
        </tr>
      </thead>

      <!-- 表格内容 -->
      <tbody>
        <!-- 空数据提示 -->
        <tr v-if="dataSource.length === 0">
          <td :colspan="showCheckbox ? columns.length + 1 : columns.length"
            class="text-center p-4 text-gray-500 border-b border-[#e5e6eb]">
            暂无数据
          </td>
        </tr>

        <!-- 数据行：循环渲染dataSource -->
        <tr v-else class="table-basic-row transition-colors" v-for="(item, dataIndex) in dataSource"
          :key="item.id || dataIndex">
          <!-- 多选框/单选框单元格 -->
          <td v-if="showCheckbox" :style="checkboxStyle"
            class="p-[10px_8px_10px_14px] border-b border-[#e5e6eb] transition-all">
            <div class="flex items-center justify-center">
              <!-- 隐藏原生复选框 -->
              <input type="checkbox" class="hidden" :value="item.id" v-model="selectedIds"
                @change="handleSelect(item.id)" />
              <!-- 自定义复选框样式 -->
              <div
                class="w-4 h-4 border border-gray-300 rounded cursor-pointer flex items-center justify-center transition-colors"
                :class="{ 'bg-blue-500 border-blue-500': selectedIds.includes(item.id) }"
                @click="handleSelect(item.id)">
                <span v-if="selectedIds.includes(item.id)" class="text-white text-xs">✓</span>
              </div>
            </div>
          </td>

          <!-- 数据单元格：支持插槽自定义内容 -->
          <td v-for="(column, index) in columns" :key="column.dataIndex || index" :style="columnStyles[index]"
            class="p-[10px_8px_10px_14px] border-b border-[#e5e6eb] transition-all">
            <!-- 插槽优先级：有自定义插槽则渲染插槽，否则渲染默认字段值 -->
            <template v-if="$slots[column.dataIndex]">
              <slot :name="column.dataIndex" :item="item" :dataIndex="dataIndex" />
            </template>
            <template v-else>
              <!-- 支持嵌套字段（如column.dataIndex为"user.name"） -->
              {{column.dataIndex.split('.').reduce((obj, key) => obj?.[key] ?? '', item)}}
            </template>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<style scoped>
/* 行 hover 效果 */
.table-basic-row:hover {
  background-color: #f8f8f8;
}

/* 防止表格内容溢出 */
td,
th {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
</style>